/**
 * 用户管理页面
 * 支持创建/编辑、批量操作、乐观状态更新
 */

import React from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import {
  Container,
} from '@/components/ui/container';
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Badge } from '@/components/ui/badge';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  ResponsiveTable,
  ResponsiveTableHeader,
  ResponsiveTableRow,
  ResponsiveTableHead,
  ResponsiveTableCell,
  TableLoading,
  TableEmpty,
} from '@/components/ui/responsive-table';
import { TableBody } from '@/components/ui/table';
import { Checkbox } from '@/components/ui/checkbox';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
  FormDialog,
  BatchActionBar,
} from '@/components/system';
import { UserForm } from './components/user-form.jsx';
import {
  adminUserService,
  adminRoleService,
} from '@/lib/api/services/admin-management-service.js';
import { useAdminMutation } from '@/hooks/use-admin-mutation.js';
import {
  Search,
  RefreshCw,
  UserCheck,
  Users,
  Plus,
  Trash2,
  ShieldCheck,
  Ban,
  EllipsisVertical,
} from 'lucide-react';

const STATUS_FILTER_OPTIONS = [
  { label: '全部状态', value: 'all' },
  { label: '启用', value: 'active' },
  { label: '禁用', value: 'inactive' },
  { label: '封禁', value: 'banned' },
];

const VERIFIED_OPTIONS = [
  { label: '邮箱验证状态', value: 'all' },
  { label: '已验证', value: 'true' },
  { label: '未验证', value: 'false' },
];

const STATUS_VARIANT = {
  active: 'default',
  inactive: 'secondary',
  banned: 'destructive',
};

const STATUS_LABEL = {
  active: '启用',
  inactive: '禁用',
  banned: '封禁',
};

const formatDateTime = (value) => {
  if (!value) return '-';
  try {
    return new Date(value).toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
    });
  } catch (error) {
    return value;
  }
};

export default function UserManagementPage() {
  const queryClient = useQueryClient();

  const [page, setPage] = React.useState(1);
  const [pageSize] = React.useState(20);
  const [keyword, setKeyword] = React.useState('');
  const [status, setStatus] = React.useState('all');
  const [roleId, setRoleId] = React.useState('all');
  const [emailVerified, setEmailVerified] = React.useState('all');
  const [selectedIds, setSelectedIds] = React.useState([]);

  const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false);
  const [isEditDialogOpen, setIsEditDialogOpen] = React.useState(false);
  const [editingUserId, setEditingUserId] = React.useState(null);
  const [editingUser, setEditingUser] = React.useState(null);
  const [isLoadingUserDetail, setIsLoadingUserDetail] = React.useState(false);

  const queryParams = React.useMemo(() => {
    const params = { page, pageSize };
    if (keyword.trim()) params.keyword = keyword.trim();
    if (status !== 'all') params.status = status;
    if (roleId !== 'all') params.roleId = roleId;
    if (emailVerified !== 'all') params.emailVerified = emailVerified === 'true';
    return params;
  }, [page, pageSize, keyword, status, roleId, emailVerified]);

  const currentQueryKey = React.useMemo(
    () => ['admin-users', queryParams],
    [queryParams],
  );

  const {
    data: usersData,
    isLoading,
    error,
    refetch,
  } = useQuery({
    queryKey: currentQueryKey,
    queryFn: () => adminUserService.getList(queryParams),
    keepPreviousData: true,
  });

  const { data: rolesData } = useQuery({
    queryKey: ['admin-roles', 'options'],
    queryFn: () =>
      adminRoleService.getList({
        page: 1,
        pageSize: 100,
        sortBy: 'sortOrder',
        sortOrder: 'asc',
      }),
    staleTime: 5 * 60 * 1000,
  });

  const users = usersData?.data ?? [];
  const meta = {
    page: usersData?.page ?? page,
    pageSize: usersData?.pageSize ?? pageSize,
    total: usersData?.total ?? 0,
    totalPages: usersData?.totalPages ?? 1,
  };
  const roleOptions = React.useMemo(() => {
    const roles = rolesData?.data ?? [];
    return roles.map((role) => ({
      label: role.displayName || role.name,
      value: String(role.id),
    }));
  }, [rolesData]);

  React.useEffect(() => {
    if (page > meta.totalPages && meta.totalPages > 0) {
      setPage(meta.totalPages);
    }
  }, [meta.totalPages, page]);

  React.useEffect(() => {
    setSelectedIds((prev) => {
      // 仅当现有选中项在用户列表中已失效时才更新，避免引发无效的 state 更新循环
      const filtered = prev.filter((id) =>
        users.some((user) => user.id === id),
      );
      // 如果过滤后与原数组完全一致，则返回原引用，阻止 React 触发额外渲染
      const unchanged =
        filtered.length === prev.length &&
        filtered.every((id, index) => id === prev[index]);
      return unchanged ? prev : filtered;
    });
  }, [users]);

  const createUserMutation = useAdminMutation(
    (payload) => adminUserService.create(payload),
    {
      invalidateKeys: [['admin-users']],
      successMessage: '用户创建成功',
      onSuccess: () => {
        setIsCreateDialogOpen(false);
      },
    },
  );

  const updateUserMutation = useAdminMutation(
    ({ id, payload }) => adminUserService.update(id, payload),
    {
      invalidateKeys: [['admin-users']],
      successMessage: '用户信息已更新',
      onSuccess: () => {
        setIsEditDialogOpen(false);
        setEditingUserId(null);
        setEditingUser(null);
      },
    },
  );

  const updateStatusMutation = useAdminMutation(
    ({ id, status: nextStatus }) =>
      adminUserService.updateStatus(id, { status: nextStatus }),
    {
      invalidateKeys: [['admin-users']],
      successMessage: (_, { status: nextStatus }) =>
        `已更新状态为 ${STATUS_LABEL[nextStatus] ?? nextStatus}`,
      onMutate: async ({ id, status: nextStatus }) => {
        await queryClient.cancelQueries({ queryKey: currentQueryKey });
        const previousData = queryClient.getQueryData(currentQueryKey);
        queryClient.setQueryData(currentQueryKey, (old) => {
          if (!old) return old;
          return {
            ...old,
            data: old.data.map((user) =>
              user.id === id ? { ...user, status: nextStatus } : user,
            ),
          };
        });
        return { previousData };
      },
      onError: (error, _variables, context) => {
        if (context?.previousData) {
          queryClient.setQueryData(currentQueryKey, context.previousData);
        }
      },
      onSettled: () => {
        queryClient.invalidateQueries({ queryKey: ['admin-users'] });
      },
    },
  );

  const deleteUserMutation = useAdminMutation(
    (id) => adminUserService.remove(id),
    {
      invalidateKeys: [['admin-users']],
      successMessage: '用户已删除',
      onMutate: async (id) => {
        await queryClient.cancelQueries({ queryKey: currentQueryKey });
        const previousData = queryClient.getQueryData(currentQueryKey);
        queryClient.setQueryData(currentQueryKey, (old) => {
          if (!old) return old;
          return {
            ...old,
            data: old.data.filter((user) => user.id !== id),
          };
        });
        return { previousData };
      },
      onError: (_error, _id, context) => {
        if (context?.previousData) {
          queryClient.setQueryData(currentQueryKey, context.previousData);
        }
      },
      onSuccess: (_data, id) => {
        setSelectedIds((prev) => prev.filter((item) => item !== id));
      },
      onSettled: () => {
        queryClient.invalidateQueries({ queryKey: ['admin-users'] });
      },
    },
  );

  const batchStatusMutation = useAdminMutation(
    async ({ ids, status: targetStatus }) => {
      await Promise.all(
        ids.map((id) => adminUserService.updateStatus(id, { status: targetStatus })),
      );
      return targetStatus;
    },
    {
      invalidateKeys: [['admin-users']],
      successMessage: (_, { status: targetStatus }) =>
        `已批量更新为 ${STATUS_LABEL[targetStatus] ?? targetStatus}`,
      onSuccess: () => {
        setSelectedIds([]);
      },
    },
  );

  const batchDeleteMutation = useAdminMutation(
    async ({ ids }) => {
      await Promise.all(ids.map((id) => adminUserService.remove(id)));
      return ids;
    },
    {
      invalidateKeys: [['admin-users']],
      successMessage: '已批量删除用户',
      onMutate: async ({ ids }) => {
        await queryClient.cancelQueries({ queryKey: currentQueryKey });
        const previousData = queryClient.getQueryData(currentQueryKey);
        queryClient.setQueryData(currentQueryKey, (old) => {
          if (!old) return old;
          return {
            ...old,
            data: old.data.filter((user) => !ids.includes(user.id)),
          };
        });
        return { previousData };
      },
      onError: (_error, _variables, context) => {
        if (context?.previousData) {
          queryClient.setQueryData(currentQueryKey, context.previousData);
        }
      },
      onSuccess: () => {
        setSelectedIds([]);
      },
      onSettled: () => {
        queryClient.invalidateQueries({ queryKey: ['admin-users'] });
      },
    },
  );

  const isMutating =
    createUserMutation.isPending || updateUserMutation.isPending;

  const handleOpenEdit = React.useCallback(async (id) => {
    setEditingUserId(id);
    setIsEditDialogOpen(true);
    setIsLoadingUserDetail(true);
    try {
      const detail = await adminUserService.getDetail(id);
      setEditingUser(detail);
    } catch (err) {
      setIsEditDialogOpen(false);
      setEditingUserId(null);
      toast.error(err?.message ?? '加载用户详情失败');
    } finally {
      setIsLoadingUserDetail(false);
    }
  }, []);

  const handleStatusChange = React.useCallback(
    (user, nextStatus) => {
      if (user.status === nextStatus) return;
      updateStatusMutation.mutate({ id: user.id, status: nextStatus });
    },
    [updateStatusMutation],
  );

  const handleDelete = React.useCallback(
    (id) => {
      if (!id) return;
      deleteUserMutation.mutate(id);
    },
    [deleteUserMutation],
  );

  const allRowIds = users.map((user) => user.id);
  const allSelected =
    allRowIds.length > 0 &&
    allRowIds.every((id) => selectedIds.includes(id));
  const partiallySelected =
    selectedIds.length > 0 && !allSelected;

  const handleToggleAll = (checked) => {
    if (checked) {
      setSelectedIds(allRowIds);
    } else {
      setSelectedIds([]);
    }
  };

  const handleToggleOne = (id, checked) => {
    setSelectedIds((prev) => {
      if (checked) {
        return prev.includes(id) ? prev : [...prev, id];
      }
      return prev.filter((item) => item !== id);
    });
  };

  const toolbarActions = [
    {
      key: 'activate',
      icon: ShieldCheck,
      label: '批量启用',
      onClick: () =>
        batchStatusMutation.mutate({
          ids: selectedIds,
          status: 'active',
        }),
      disabled: selectedIds.length === 0 || batchStatusMutation.isPending,
    },
    {
      key: 'disable',
      icon: Ban,
      label: '批量禁用',
      onClick: () =>
        batchStatusMutation.mutate({
          ids: selectedIds,
          status: 'inactive',
        }),
      disabled: selectedIds.length === 0 || batchStatusMutation.isPending,
    },
    {
      key: 'delete',
      icon: Trash2,
      label: '批量删除',
      variant: 'destructive',
      onClick: () =>
        batchDeleteMutation.mutate({
          ids: selectedIds,
        }),
      disabled: selectedIds.length === 0 || batchDeleteMutation.isPending,
    },
  ];

  return (
    <Container>
      <div className="flex flex-wrap items-center justify-between gap-3 mb-6">
        <div>
          <h1 className="text-3xl font-bold flex items-center gap-2">
            <Users className="size-6 text-primary" />
            用户管理
          </h1>
          <p className="text-muted-foreground mt-1">
            共 {meta.total} 名用户，可按状态、角色、邮箱验证等条件筛选
          </p>
        </div>
        <div className="flex items-center gap-2">
          <Button
            variant="outline"
            onClick={() => refetch()}
            disabled={isLoading}
          >
            <RefreshCw className="size-4 mr-2" />
            刷新
          </Button>
          <Button onClick={() => setIsCreateDialogOpen(true)}>
            <Plus className="size-4 mr-1.5" />
            新建用户
          </Button>
        </div>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>用户列表</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid grid-cols-1 lg:grid-cols-5 gap-4">
            <div className="col-span-1 lg:col-span-2 relative">
              <Search className="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                placeholder="搜索邮箱 / 用户名 / 姓名"
                value={keyword}
                onChange={(event) => {
                  setKeyword(event.target.value);
                  setPage(1);
                }}
                className="pl-10"
              />
            </div>

            <Select
              value={status}
              onValueChange={(value) => {
                setStatus(value);
                setPage(1);
              }}
            >
              <SelectTrigger>
                <SelectValue placeholder="用户状态" />
              </SelectTrigger>
              <SelectContent>
                {STATUS_FILTER_OPTIONS.map((option) => (
                  <SelectItem key={option.value} value={option.value}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>

            <Select
              value={roleId}
              onValueChange={(value) => {
                setRoleId(value);
                setPage(1);
              }}
            >
              <SelectTrigger>
                <SelectValue placeholder="所属角色" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">全部角色</SelectItem>
                {roleOptions.map((option) => (
                  <SelectItem key={option.value} value={option.value}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>

            <Select
              value={emailVerified}
              onValueChange={(value) => {
                setEmailVerified(value);
                setPage(1);
              }}
            >
              <SelectTrigger>
                <SelectValue placeholder="邮箱验证状态" />
              </SelectTrigger>
              <SelectContent>
                {VERIFIED_OPTIONS.map((option) => (
                  <SelectItem key={option.value} value={option.value}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>

            <Button
              variant="outline"
              onClick={() => {
                setKeyword('');
                setStatus('all');
                setRoleId('all');
                setEmailVerified('all');
                setPage(1);
              }}
            >
              清除筛选
            </Button>
          </div>

          <BatchActionBar
            selectedCount={selectedIds.length}
            onClear={() => setSelectedIds([])}
            actions={toolbarActions}
          />

          <ResponsiveTable>
            <ResponsiveTableHeader>
              <ResponsiveTableRow>
                <ResponsiveTableHead className="w-[48px]">
                  <Checkbox
                    checked={allSelected ? true : partiallySelected ? 'indeterminate' : false}
                    onCheckedChange={handleToggleAll}
                    aria-label="选择全部"
                  />
                </ResponsiveTableHead>
                <ResponsiveTableHead>用户</ResponsiveTableHead>
                <ResponsiveTableHead hideOnMobile>角色</ResponsiveTableHead>
                <ResponsiveTableHead hideOnMobile>邮箱验证</ResponsiveTableHead>
                <ResponsiveTableHead hideOnTablet>状态</ResponsiveTableHead>
                <ResponsiveTableHead hideOnMobile>额外权限</ResponsiveTableHead>
                <ResponsiveTableHead hideOnMobile>创建时间</ResponsiveTableHead>
                <ResponsiveTableHead className="w-[100px] text-right">
                  操作
                </ResponsiveTableHead>
              </ResponsiveTableRow>
            </ResponsiveTableHeader>

            <TableBody>
              {isLoading ? (
                <TableLoading rows={5} columns={8} />
              ) : error ? (
                <ResponsiveTableRow>
                  <ResponsiveTableCell colSpan={8} className="py-10 text-center">
                    <p className="text-destructive mb-4">
                      加载失败：{error.message}
                    </p>
                    <Button variant="outline" onClick={() => refetch()}>
                      重试
                    </Button>
                  </ResponsiveTableCell>
                </ResponsiveTableRow>
              ) : users.length === 0 ? (
                <TableEmpty
                  colSpan={8}
                  icon={UserCheck}
                  title="暂无用户数据"
                  description="尝试调整筛选条件或稍后再试。"
                />
              ) : (
                users.map((user) => {
                  const selected = selectedIds.includes(user.id);
                  return (
                    <ResponsiveTableRow key={user.id}>
                      <ResponsiveTableCell className="w-[48px]">
                        <Checkbox
                          checked={selected}
                          onCheckedChange={(checked) =>
                            handleToggleOne(user.id, checked)
                          }
                          aria-label="选择用户"
                        />
                      </ResponsiveTableCell>

                      <ResponsiveTableCell className="space-y-1">
                        <div className="font-medium">
                          {user.fullName || '未填写姓名'}
                        </div>
                        <div className="text-xs text-muted-foreground break-all">
                          {user.email}
                        </div>
                        <div className="text-xs text-muted-foreground">
                          用户名：{user.username}
                        </div>
                      </ResponsiveTableCell>

                      <ResponsiveTableCell hideOnMobile>
                        {user.role ? (
                          <Badge variant="secondary">
                            {user.role.displayName || user.role.name}
                          </Badge>
                        ) : (
                          <span className="text-xs text-muted-foreground">
                            未分配角色
                          </span>
                        )}
                      </ResponsiveTableCell>

                      <ResponsiveTableCell hideOnMobile>
                        <Badge variant={user.emailVerified ? 'default' : 'outline'}>
                          {user.emailVerified ? '已验证' : '未验证'}
                        </Badge>
                      </ResponsiveTableCell>

                      <ResponsiveTableCell hideOnTablet>
                        <Badge variant={STATUS_VARIANT[user.status] || 'outline'}>
                          {STATUS_LABEL[user.status] ?? user.status}
                        </Badge>
                      </ResponsiveTableCell>

                      <ResponsiveTableCell hideOnMobile>
                        {user.extraPermissionIds?.length || 0}
                      </ResponsiveTableCell>

                      <ResponsiveTableCell hideOnMobile>
                        <div className="text-sm text-muted-foreground">
                          {formatDateTime(user.createdAt)}
                        </div>
                        <div className="text-xs text-muted-foreground">
                          最近登录：{formatDateTime(user.lastSignInAt)}
                        </div>
                      </ResponsiveTableCell>

                      <ResponsiveTableCell className="text-right">
                        <DropdownMenu>
                          <DropdownMenuTrigger asChild>
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-8 w-8"
                            >
                              <EllipsisVertical className="size-4" />
                            </Button>
                          </DropdownMenuTrigger>
                          <DropdownMenuContent align="end">
                            <DropdownMenuItem onClick={() => handleOpenEdit(user.id)}>
                              编辑
                            </DropdownMenuItem>
                            <DropdownMenuItem
                              onClick={() =>
                                handleStatusChange(
                                  user,
                                  user.status === 'active' ? 'inactive' : 'active',
                                )
                              }
                            >
                              {user.status === 'active' ? '禁用' : '启用'}
                            </DropdownMenuItem>
                            <DropdownMenuItem
                              onClick={() => handleStatusChange(user, 'banned')}
                            >
                              封禁
                            </DropdownMenuItem>
                            <DropdownMenuItem
                              onClick={() => handleDelete(user.id)}
                              className="text-destructive focus:text-destructive"
                            >
                              删除
                            </DropdownMenuItem>
                          </DropdownMenuContent>
                        </DropdownMenu>
                      </ResponsiveTableCell>
                    </ResponsiveTableRow>
                  );
                })
              )}
            </TableBody>
          </ResponsiveTable>

          {meta.totalPages > 1 && (
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div className="text-sm text-muted-foreground">
                第 {(meta.page - 1) * meta.pageSize + 1} -
                {' '}
                {Math.min(meta.page * meta.pageSize, meta.total)} 条 / 共 {meta.total} 条
              </div>
              <div className="flex items-center gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  disabled={meta.page <= 1}
                  onClick={() => setPage((prev) => Math.max(prev - 1, 1))}
                >
                  上一页
                </Button>
                <span className="text-sm text-muted-foreground">
                  {meta.page} / {meta.totalPages}
                </span>
                <Button
                  variant="outline"
                  size="sm"
                  disabled={meta.page >= meta.totalPages}
                  onClick={() => setPage((prev) => Math.min(prev + 1, meta.totalPages))}
                >
                  下一页
                </Button>
              </div>
            </div>
          )}
        </CardContent>
      </Card>

      <FormDialog
        open={isCreateDialogOpen}
        onOpenChange={(open) => {
          setIsCreateDialogOpen(open);
        }}
        title="新建用户"
        description="填写基础信息并为用户分配角色"
        size="lg"
      >
        <UserForm
          mode="create"
          roleOptions={roleOptions}
          onSubmit={(payload) => createUserMutation.mutate(payload)}
          onCancel={() => setIsCreateDialogOpen(false)}
          isSubmitting={createUserMutation.isPending}
        />
      </FormDialog>

      <FormDialog
        open={isEditDialogOpen}
        onOpenChange={(open) => {
          if (!open) {
            setIsEditDialogOpen(false);
            setEditingUserId(null);
            setEditingUser(null);
          }
        }}
        title="编辑用户"
        description="调整用户基本信息或重置密码"
        size="lg"
      >
        {isLoadingUserDetail ? (
          <div className="py-10 text-center text-sm text-muted-foreground">
            正在加载用户信息…
          </div>
        ) : editingUser ? (
          <UserForm
            mode="edit"
            defaultValues={editingUser}
            roleOptions={roleOptions}
            onSubmit={(payload) =>
              updateUserMutation.mutate({
                id: editingUserId,
                payload,
              })
            }
            onCancel={() => {
              setIsEditDialogOpen(false);
              setEditingUserId(null);
              setEditingUser(null);
            }}
            isSubmitting={isMutating}
          />
        ) : (
          <div className="py-10 text-center text-sm text-muted-foreground">
            未找到用户信息，可能已经被删除。
          </div>
        )}
      </FormDialog>
    </Container>
  );
}

